/* Endless Code Copyright (C) 2009 Jingul,Kim
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package ec.util;

/**
 * 
 * 
 * @since 2009
 * @version 1.0
 * @author <a href="mailto:jingul.kim@gmail.com">Jingul,Kim</a>
 */
public class Matrix {
	private float[] e;

	public Matrix() {
		init();
	}

	public Matrix(float[] matrix) {
		if (matrix.length == 16) {
			e = matrix;
			return;
		}

		init();
	}

	private void init() {
		e = new float[16];

		e[0] = 1.0f;
		e[5] = 1.0f;
		e[10] = 1.0f;
		e[15] = 1.0f;
	}

	public float[] getArray() {
		return e;
	}
	
	public float get(int c) {
		return e[c];
	}
	
	public void set(int c, float e) {
		this.e[c] = e;
	}
	
	public void add(int c, float e) {
		this.e[c] += e;
	}
	
	public void scalar(float s) {
		
	}

	public void identity() {
		e[0] = 1.0f;
		e[1] = 0.0f;
		e[2] = 0.0f;
		e[3] = 0.0f;

		e[4] = 0.0f;
		e[5] = 1.0f;
		e[6] = 0.0f;
		e[7] = 0.0f;

		e[8] = 0.0f;
		e[9] = 0.0f;
		e[10] = 1.0f;
		e[11] = 0.0f;

		e[12] = 0.0f;
		e[13] = 0.0f;
		e[14] = 0.0f;
		e[15] = 1.0f;
	}

	public Matrix multi(Matrix b) {
		Matrix dst = new Matrix();
		multi(dst.e, e, b.e);

		return dst;
	}
	
	public void multi(Matrix dst, Matrix b) {
		multi(dst.e, e, b.e);
	}
	
	
	public static float[] multi(float[] a, float[] b)
	{
		float[] dst = new float[16];
		multi(dst, a, b);
		return dst;
	}
	
	public static void multi(float[] dst, float[] a, float[] b)
	{
		dst[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2];
		dst[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2];
		dst[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2];
		dst[3] = 0.0f;

		dst[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6];
		dst[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6];
		dst[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6];
		dst[7] = 0.0f;

		dst[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10];
		dst[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10];
		dst[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10];
		dst[11] = 0.0f;

		dst[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12];
		dst[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13];
		dst[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14];
		dst[15] = 1.0f;
	}
	
	public static void inverse(Matrix dst, float[] e)
	{
		inverse(dst.e, e);
	}
	
	public static void inverse(float[] dst, float[] e)
	{
		float det;

		dst[0] = e[5] * e[10] - e[9] * e[6];
		dst[1] = e[9] * e[2] - e[1] * e[10];
		dst[2] = e[1] * e[6] - e[5] * e[2];

		det = e[0] * dst[0] + e[4] * dst[1] + e[8] * dst[2];

		dst[0] /= det;
		dst[1] /= det;
		dst[2] /= det;
		dst[3] = 0.0f;

		dst[4] = (e[8] * e[6] - e[4] * e[10]) / det;
		dst[5] = (e[0] * e[10] - e[8] * e[2]) / det;
		dst[6] = (e[4] * e[2] - e[0] * e[6]) / det;
		dst[7] = 0.0f;

		dst[8] = (e[4] * e[9] - e[8] * e[5]) / det;
		dst[9] = (e[8] * e[1] - e[0] * e[9]) / det;
		dst[10] = (e[0] * e[5] - e[4] * e[1]) / det;
		dst[11] = 0.0f;

		dst[12] = -(dst[0] * e[12] + dst[4] * e[13] + dst[8] * e[14]);
		dst[13] = -(dst[1] * e[12] + dst[5] * e[13] + dst[9] * e[14]);
		dst[14] = -(dst[2] * e[12] + dst[6] * e[13] + dst[10] * e[14]);
		dst[15] = 1.0f;
	}
	
	public static void rotation(float angle, Vector v) {
		
	}
	
	public static void rotation(float angle, float x, float y, float z) {
		
	}
	
	public static void translate(float x, float y, float z) {
		
	}
}
